#include <iostream>

#include <memory> //智能指针

using namespace std;


class BBB
{
public:
    BBB()
    {

    }
    ~BBB()
    {
         std::cout << "BBB xigou" << std::endl;
    }
};

std::unique_ptr<BBB> func1(std::unique_ptr<BBB> p)
{
    return p;
}

std::unique_ptr<BBB> func2(std::unique_ptr<BBB> p)
{
//    return p;
}




int main()
{
    cout << "Hello World!" << endl;

    //std::auto_ptr尴尬的地方在于，保证指针持有者唯一（类似于unique_ptr）
    //但是他支持p1=p2的操作，这样会导致p2为空，也就是说，复制和赋值会改变资源的所有权，不符合人的直觉。


    //智能指针测试
    {
        std::unique_ptr<BBB> p1(new BBB());
        std::unique_ptr<BBB> p2;

        p2 = std::unique_ptr<BBB>(new BBB());
        std::unique_ptr<BBB> p3(new BBB());

        p1 = nullptr;
        p2.release();//放弃对它所指对象的控制权，并返回保存的指针，将up置为空，不会释放内存
//        p3.reset(nullptr);
        p3.reset(new BBB());//参数可以为空或者内置指针（即传统的裸指针），先将up所指对象释放，然后重置up的值


        func1((std::unique_ptr<BBB>)p3.release());
        func1(std::unique_ptr<BBB>(new BBB()));
        func1((std::unique_ptr<BBB>)new BBB());


        std::unique_ptr<BBB> p4(new BBB());
        std::unique_ptr<BBB> p5(new BBB());
        p4 = std::move(p5);//转移所有权，之后p5指向空，p4会释放原有内存，然后持有新对象
        p4.swap(p5);//交换被管理对象和关联的删除器。


        std::cout << "test end" << std::endl;
    }


    //shared_ptr若循环引用，会导致内存泄漏
    {
        std::shared_ptr<BBB> p1;
        std::shared_ptr<BBB> p2(new BBB());
        std::shared_ptr<BBB> p3(p2);//引用计数加1
        std::shared_ptr<BBB> p4 = std::make_shared<BBB>();//一般用这个进行初始化

        std::shared_ptr<int> p5 = std::make_shared<int>(10);
        std::shared_ptr<int> p6 = std::make_shared<int>(11);

        p5 = p6;//int(10)引用计数减一到0，然后会销毁，int(11)引用计数加1，为2
        p6 = nullptr;//引用计数减一

        std::shared_ptr<int> p7 = std::make_shared<int>(12);
        p7.reset();//引用计数减一

        p6 = std::make_shared<int>(13);
        p6.reset(new int(12));//p6原对象引用计数减一，然后接管新对象，新对象必须为内置指针（裸指针）

        p6.use_count();//返回引用计数，可能会很慢，主要用于调试，多线程环境下， use_count 返回的值是近似的


        //weak_ptr使用
        //weak_ptr不能直接访问对象，必须提升为shared_ptr后访问
        std::shared_ptr<int> p10 = std::make_shared<int>(21);
        std::weak_ptr<int> wp1(p10);//引用计数不变

        //lock提升为shared_ptr；若引用计数为0，提升失败，返回空shared_ptr，否则返回其对象的shared_ptr，此时引用计数加1
        std::shared_ptr<int> p11 = wp1.lock();

        wp1.expired();    // 检测对象是否已经释放，如果已经释放，返回true；否则返回false
        wp1.use_count();  // 返回对象的引用计数
        wp1.reset();// 置空weak_ptr
    }










    return 0;
}
